1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31 import sun.misc.FpUtils;
32 import sun.misc.DoubleConsts;
33
34 public class CubeRootTests {
35 private CubeRootTests(){}
36
37 static final double infinityD = Double.POSITIVE_INFINITY;
38 static final double NaNd = Double.NaN;
39
40
41 static java.util.Random rand = new java.util.Random();
42
43 static int testCubeRootCase(double input, double expected) {
44 int failures=0;
45
46 double minus_input = -input;
47 double minus_expected = -expected;
48
49 failures+=Tests.test("Math.cbrt(double)", input,
50 Math.cbrt(input), expected);
51 failures+=Tests.test("Math.cbrt(double)", minus_input,
52 Math.cbrt(minus_input), minus_expected);
53 failures+=Tests.test("StrictMath.cbrt(double)", input,
54 StrictMath.cbrt(input), expected);
55 failures+=Tests.test("StrictMath.cbrt(double)", minus_input,
56 StrictMath.cbrt(minus_input), minus_expected);
57
58 return failures;
59 }
60
61 static int testCubeRoot() {
62 int failures = 0;
63 double [][] testCases = {
64 {NaNd, NaNd},
65 {Double.longBitsToDouble(0x7FF0000000000001L), NaNd},
66 {Double.longBitsToDouble(0xFFF0000000000001L), NaNd},
67 {Double.longBitsToDouble(0x7FF8555555555555L), NaNd},
68 {Double.longBitsToDouble(0xFFF8555555555555L), NaNd},
69 {Double.longBitsToDouble(0x7FFFFFFFFFFFFFFFL), NaNd},
70 {Double.longBitsToDouble(0xFFFFFFFFFFFFFFFFL), NaNd},
71 {Double.longBitsToDouble(0x7FFDeadBeef00000L), NaNd},
72 {Double.longBitsToDouble(0xFFFDeadBeef00000L), NaNd},
73 {Double.longBitsToDouble(0x7FFCafeBabe00000L), NaNd},
74 {Double.longBitsToDouble(0xFFFCafeBabe00000L), NaNd},
75 {Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY},
76 {Double.NEGATIVE_INFINITY, Double.NEGATIVE_INFINITY},
77 {+0.0, +0.0},
78 {-0.0, -0.0},
79 {+1.0, +1.0},
80 {-1.0, -1.0},
81 {+8.0, +2.0},
82 {-8.0, -2.0}
83 };
84
85 for(int i = 0; i < testCases.length; i++) {
86 failures += testCubeRootCase(testCases[i][0],
87 testCases[i][1]);
88 }
89
90
91 for(int i = 0; i <= 208063; i++) {
92 double d = i;
93 failures += testCubeRootCase(d*d*d, (double)i);
94 }
95
96
97 for(int i = 18; i <= DoubleConsts.MAX_EXPONENT/3; i++) {
98 failures += testCubeRootCase(FpUtils.scalb(1.0, 3*i),
99 FpUtils.scalb(1.0, i) );
100 }
101
102
103 for(int i = -1; i >= FpUtils.ilogb(Double.MIN_VALUE)/3; i--) {
104 failures += testCubeRootCase(FpUtils.scalb(1.0, 3*i),
105 FpUtils.scalb(1.0, i) );
106 }
107
108
109
110
111
112 long exponentBits1 =
113 Double.doubleToLongBits(FpUtils.scalb(1.0, 55)) &
114 DoubleConsts.EXP_BIT_MASK;
115 long exponentBits2=
116 Double.doubleToLongBits(FpUtils.scalb(1.0, -55)) &
117 DoubleConsts.EXP_BIT_MASK;
118 for(int i = 0; i < 100; i++) {
119
120
121 double input1 =
122 Double.longBitsToDouble(exponentBits1 |
123
124 ((long) (rand.nextInt() & 0xFFFF))<<
125 (DoubleConsts.SIGNIFICAND_WIDTH-1-16));
126 failures += testCubeRootCase(input1*input1*input1, input1);
127
128 double input2 =
129 Double.longBitsToDouble(exponentBits2 |
130
131 ((long) (rand.nextInt() & 0xFFFF))<<
132 (DoubleConsts.SIGNIFICAND_WIDTH-1-16));
133 failures += testCubeRootCase(input2*input2*input2, input2);
134 }
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171 for(int i = 0; i < 1000; i++) {
172 double d = 1.0 + rand.nextDouble();
173 double err, err_adjacent;
174
175 double y1 = Math.cbrt(d);
176 double y2 = StrictMath.cbrt(d);
177
178 err = d - StrictMath.pow(y1, 3);
179 if (err != 0.0) {
180 if(FpUtils.isNaN(err)) {
181 failures++;
182 System.err.println("Encountered unexpected NaN value: d = " + d +
183 "\tcbrt(d) = " + y1);
184 } else {
185 if (err < 0.0) {
186 err_adjacent = StrictMath.pow(FpUtils.nextUp(y1), 3) - d;
187 }
188 else {
189 err_adjacent = StrictMath.pow(FpUtils.nextAfter(y1,0.0), 3) - d;
190 }
191
192 if (Math.abs(err) > Math.abs(err_adjacent)) {
193 failures++;
194 System.err.println("For Math.cbrt(" + d + "), returned result " +
195 y1 + "is not as good as adjacent value.");
196 }
197 }
198 }
199
200
201 err = d - StrictMath.pow(y2, 3);
202 if (err != 0.0) {
203 if(FpUtils.isNaN(err)) {
204 failures++;
205 System.err.println("Encountered unexpected NaN value: d = " + d +
206 "\tcbrt(d) = " + y2);
207 } else {
208 if (err < 0.0) {
209 err_adjacent = StrictMath.pow(FpUtils.nextUp(y2), 3) - d;
210 }
211 else {
212 err_adjacent = StrictMath.pow(FpUtils.nextAfter(y2,0.0), 3) - d;
213 }
214
215 if (Math.abs(err) > Math.abs(err_adjacent)) {
216 failures++;
217 System.err.println("For StrictMath.cbrt(" + d + "), returned result " +
218 y2 + "is not as good as adjacent value.");
219 }
220 }
221 }
222
223
224 }
225
226
227
228
229
230
231
232
233
234
235
236
237 {
238
239 double pcNeighbors[] = new double[5];
240 double pcNeighborsCbrt[] = new double[5];
241 double pcNeighborsStrictCbrt[] = new double[5];
242
243
244 for(int i = 18; i <= DoubleConsts.MAX_EXPONENT/3; i++) {
245 double pc = FpUtils.scalb(1.0, 3*i);
246
247 pcNeighbors[2] = pc;
248 pcNeighbors[1] = FpUtils.nextDown(pc);
249 pcNeighbors[0] = FpUtils.nextDown(pcNeighbors[1]);
250 pcNeighbors[3] = FpUtils.nextUp(pc);
251 pcNeighbors[4] = FpUtils.nextUp(pcNeighbors[3]);
252
253 for(int j = 0; j < pcNeighbors.length; j++) {
254 pcNeighborsCbrt[j] = Math.cbrt(pcNeighbors[j]);
255 pcNeighborsStrictCbrt[j] = StrictMath.cbrt(pcNeighbors[j]);
256 }
257
258 for(int j = 0; j < pcNeighborsCbrt.length-1; j++) {
259 if(pcNeighborsCbrt[j] > pcNeighborsCbrt[j+1] ) {
260 failures++;
261 System.err.println("Monotonicity failure for Math.cbrt on " +
262 pcNeighbors[j] + " and " +
263 pcNeighbors[j+1] + "\n\treturned " +
264 pcNeighborsCbrt[j] + " and " +
265 pcNeighborsCbrt[j+1] );
266 }
267
268 if(pcNeighborsStrictCbrt[j] > pcNeighborsStrictCbrt[j+1] ) {
269 failures++;
270 System.err.println("Monotonicity failure for StrictMath.cbrt on " +
271 pcNeighbors[j] + " and " +
272 pcNeighbors[j+1] + "\n\treturned " +
273 pcNeighborsStrictCbrt[j] + " and " +
274 pcNeighborsStrictCbrt[j+1] );
275 }
276
277
278 }
279
280 }
281
282
283 for(int i = -1; i >= FpUtils.ilogb(Double.MIN_VALUE)/3; i--) {
284 double pc = FpUtils.scalb(1.0, 3*i);
285
286 pcNeighbors[2] = pc;
287 pcNeighbors[1] = FpUtils.nextDown(pc);
288 pcNeighbors[0] = FpUtils.nextDown(pcNeighbors[1]);
289 pcNeighbors[3] = FpUtils.nextUp(pc);
290 pcNeighbors[4] = FpUtils.nextUp(pcNeighbors[3]);
291
292 for(int j = 0; j < pcNeighbors.length; j++) {
293 pcNeighborsCbrt[j] = Math.cbrt(pcNeighbors[j]);
294 pcNeighborsStrictCbrt[j] = StrictMath.cbrt(pcNeighbors[j]);
295 }
296
297 for(int j = 0; j < pcNeighborsCbrt.length-1; j++) {
298 if(pcNeighborsCbrt[j] > pcNeighborsCbrt[j+1] ) {
299 failures++;
300 System.err.println("Monotonicity failure for Math.cbrt on " +
301 pcNeighbors[j] + " and " +
302 pcNeighbors[j+1] + "\n\treturned " +
303 pcNeighborsCbrt[j] + " and " +
304 pcNeighborsCbrt[j+1] );
305 }
306
307 if(pcNeighborsStrictCbrt[j] > pcNeighborsStrictCbrt[j+1] ) {
308 failures++;
309 System.err.println("Monotonicity failure for StrictMath.cbrt on " +
310 pcNeighbors[j] + " and " +
311 pcNeighbors[j+1] + "\n\treturned " +
312 pcNeighborsStrictCbrt[j] + " and " +
313 pcNeighborsStrictCbrt[j+1] );
314 }
315
316
317 }
318 }
319 }
320
321 return failures;
322 }
323
324 public static void main(String argv[]) {
325 int failures = 0;
326
327 failures += testCubeRoot();
328
329 if (failures > 0) {
330 System.err.println("Testing cbrt incurred "
331 + failures + " failures.");
332 throw new RuntimeException();
333 }
334 }
335
336 }